/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
** 
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
** 
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
** 
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/


//============================================================================
//                                   INCLUDES
//============================================================================
#include "DockOverlay.h"

#include <QPointer>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QMoveEvent>
#include <QPainter>
#include <QGridLayout>
#include <QCursor>
#include <QIcon>
#include <QLabel>
#include <QtGlobal>
#include <QDebug>
#include <QMap>
#include <QWindow>

#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
#include "DockContainerWidget.h"
#include "AutoHideSideBar.h"
#include "DockManager.h"
#include "DockAreaTabBar.h"

#include <iostream>

namespace ads
{
static const int AutoHideAreaWidth = 32; // 自动隐藏区域的宽度
static const int AutoHideAreaMouseZone = 8; // 自动隐藏区域的鼠标区域
static const int InvalidTabIndex = -2; // 无效的选项卡索引

/**
 * CDockOverlay的私有数据类
 */
struct DockOverlayPrivate
{
    CDockOverlay* _this;
    DockWidgetAreas AllowedAreas = InvalidDockWidgetArea; // 允许的DockWidget区域
    CDockOverlayCross* Cross; // DockOverlayCross对象指针
    QPointer<QWidget> TargetWidget; // 目标小部件指针
    DockWidgetArea LastLocation = InvalidDockWidgetArea; // 上次位置
    bool DropPreviewEnabled = true; // 是否启用拖放预览
    CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay; // 模式
    QRect DropAreaRect; // 拖放区域矩形
    int TabIndex = InvalidTabIndex; // 选项卡索引

    /**
     * 私有数据构造函数
     */
    DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {}

    /**
     * 根据侧边栏的可见性返回覆盖层的宽度/高度
     */
    int sideBarOverlaySize(SideBarLocation sideBarLocation);

    /**
     * 侧边栏中被认为是鼠标区域的范围
     */
    int sideBarMouseZone(SideBarLocation sideBarLocation);
};

/**
 * CDockOverlayCross类的私有数据
 */
struct DockOverlayCrossPrivate
{
    CDockOverlayCross* _this;
    CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay; // 模式
    CDockOverlay* DockOverlay; // DockOverlay对象指针
    QHash<DockWidgetArea, QWidget*> DropIndicatorWidgets; // 拖放指示器小部件哈希表
    QGridLayout* GridLayout; // 网格布局
    QColor IconColors[5]; // 图标颜色数组
    bool UpdateRequired = false; // 是否需要更新
    double LastDevicePixelRatio = 0.1; // 上次设备像素比

    /**
     * 私有数据构造函数
     */
    DockOverlayCrossPrivate(CDockOverlayCross* _public) : _this(_public) {}

    /**
     * @param area
     * @return
     */
    QPoint areaGridPosition(const DockWidgetArea area);

    /**
     * 基于调色板的默认图标颜色
     */
    QColor defaultIconColor(CDockOverlayCross::eIconColor ColorIndex)
    {
        QPalette pal = _this->palette();
        switch (ColorIndex)
        {
        case CDockOverlayCross::FrameColor: return pal.color(QPalette::Active, QPalette::Highlight); // 边框颜色
        case CDockOverlayCross::WindowBackgroundColor: return pal.color(QPalette::Active, QPalette::Base); // 窗口背景颜色
        case CDockOverlayCross::OverlayColor:
            {
                QColor Color = pal.color(QPalette::Active, QPalette::Highlight);
                Color.setAlpha(64);
                return Color; // 覆盖层颜色
            }
            break;
        case CDockOverlayCross::ArrowColor: return pal.color(QPalette::Active, QPalette::Base); // 箭头颜色
        case CDockOverlayCross::ShadowColor: return QColor(0, 0, 0, 64); // 阴影颜色
        default:
            return QColor();
        }
        return QColor();
    }

    /**
     * 基于样式表的图标颜色
     */
    QColor iconColor(CDockOverlayCross::eIconColor ColorIndex)
    {
        QColor Color = IconColors[ColorIndex];
        if (!Color.isValid())
        {
            Color = defaultIconColor(ColorIndex);
            IconColors[ColorIndex] = Color;
        }
        return Color;
    }

    //============================================================================
    /**
     * 辅助函数，根据操作系统返回拖放指示器的宽度
     */
    qreal dropIndicatiorWidth(QLabel* l) const
    {
    #if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
        Q_UNUSED(l)
        return 40;
    #else
        return static_cast<qreal>(l->fontMetrics().height()) * 3.f;
    #endif
    }


	//============================================================================

/**
 * @brief 创建拖放指示器小部件
 * @param DockWidgetArea 拖放指示器所在的停靠区域
 * @param Mode 拖放指示器的模式
 * @return 拖放指示器小部件的指针
 */
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea, CDockOverlay::eMode Mode)
{
    QLabel* l = new QLabel();
    l->setObjectName("DockWidgetAreaLabel");

    qreal metric = dropIndicatiorWidth(l);
    QSizeF size(metric, metric);

    if (internal::isSideBarArea(DockWidgetArea))
    {
        auto SideBarLocation = internal::toSideBarLocation(DockWidgetArea);

        if (internal::isHorizontalSideBarLocation(SideBarLocation))
        {
            size.setHeight(size.height() / 2);
        }
        else
        {
            size.setWidth(size.width() / 2);
        }
    }

    l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode));
    l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
    l->setAttribute(Qt::WA_TranslucentBackground);
    l->setProperty("dockWidgetArea", DockWidgetArea);

    return l;
}

	//============================================================================

// 更新DropIndicatorWidget的图标
void updateDropIndicatorIcon(QWidget* DropIndicatorWidget)
{
    QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
    const qreal metric = dropIndicatiorWidth(l);
    const QSizeF size(metric, metric);
    int Area = l->property("dockWidgetArea").toInt();
    l->setPixmap(createHighDpiDropIndicatorPixmap(size, (DockWidgetArea)Area, Mode));
}

//============================================================================

// 创建高分辨率的DropIndicator图像
QPixmap createHighDpiDropIndicatorPixmap(const QSizeF& size, DockWidgetArea DockWidgetArea,
    CDockOverlay::eMode Mode)
{
    QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
    QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
    QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor);
    if (overlayColor.alpha() == 255)
    {
        overlayColor.setAlpha(64);
    }
#if QT_VERSION >= 0x050600
    double DevicePixelRatio = _this->window()->devicePixelRatioF();
#else
    double DevicePixelRatio = _this->window()->devicePixelRatio();
#endif
    QSizeF PixmapSize = size * DevicePixelRatio;
    QPixmap pm(PixmapSize.toSize());
    pm.fill(QColor(0, 0, 0, 0));
    QPainter p(&pm);
    QPen pen = p.pen();
    QRectF ShadowRect(pm.rect());
    QRectF baseRect;
    baseRect.setSize(ShadowRect.size() * 0.7);
    baseRect.moveCenter(ShadowRect.center());

    // 填充
    QColor ShadowColor = iconColor(CDockOverlayCross::ShadowColor);
    if (ShadowColor.alpha() == 255)
    {
        ShadowColor.setAlpha(64);
    }
    p.fillRect(ShadowRect, ShadowColor);

    // Drop区域矩形
    p.save();
    QRectF areaRect;
    QLineF areaLine;
    QRectF nonAreaRect;
    switch (DockWidgetArea)
    {
        case TopDockWidgetArea:
            areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
            nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
            areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
            break;
        case RightDockWidgetArea:
            areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
            nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
            areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
            break;
        case BottomDockWidgetArea:
            areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
            nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
            areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
            break;
        case LeftDockWidgetArea:
            areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
            nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
            areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
            break;
        default:
            break;
    }
    QSizeF baseSize = baseRect.size();
    bool IsOuterContainerArea = (CDockOverlay::ModeContainerOverlay == Mode)
        && (DockWidgetArea != CenterDockWidgetArea)
        && !internal::isSideBarArea(DockWidgetArea);
    if (IsOuterContainerArea)
    {
        baseRect = areaRect;
    }
    p.fillRect(baseRect, backgroundColor);
    if (areaRect.isValid())
    {
        pen = p.pen();
        pen.setColor(borderColor);
        p.setBrush(overlayColor);
        p.setPen(Qt::NoPen);
        p.drawRect(areaRect);
        pen = p.pen();
        pen.setWidth(1);
        pen.setColor(borderColor);
        pen.setStyle(Qt::DashLine);
        p.setPen(pen);
        p.drawLine(areaLine);
    }
    p.restore();
    p.save();

    // 绘制外边框
    pen = p.pen();
    pen.setColor(borderColor);
    pen.setWidth(1);
    p.setBrush(Qt::NoBrush);
    p.setPen(pen);
    p.drawRect(baseRect);

    // 绘制窗口标题栏
    p.setBrush(borderColor);
    QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
    p.drawRect(FrameRect);
    p.restore();

    // 绘制外部容器的箭头
    if (IsOuterContainerArea)
    {
        QRectF ArrowRect;
        ArrowRect.setSize(baseSize);
        ArrowRect.setWidth(ArrowRect.width() / 4.6);
        ArrowRect.setHeight(ArrowRect.height() / 2);
        ArrowRect.moveCenter(QPointF(0, 0));
        QPolygonF Arrow;
        Arrow << ArrowRect.topLeft()
            << QPointF(ArrowRect.right(), ArrowRect.center().y())
            << ArrowRect.bottomLeft();
        p.setPen(Qt::NoPen);
        p.setBrush(iconColor(CDockOverlayCross::ArrowColor));
        p.setRenderHint(QPainter::Antialiasing, true);
        p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
        switch (DockWidgetArea)
        {
            case TopDockWidgetArea:
                p.rotate(-90);
                break;
            case RightDockWidgetArea:
                break;
            case BottomDockWidgetArea:
                p.rotate(90);
                break;
            case LeftDockWidgetArea:
                p.rotate(180);
                break;
            default:
                break;
        }
        p.drawPolygon(Arrow);
    }
    pm.setDevicePixelRatio(DevicePixelRatio);
    return pm;
}


//============================================================================
// 根据侧边栏的位置计算侧边栏覆盖层的大小
int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation)
{
    auto Container = qobject_cast<CDockContainerWidget*>(TargetWidget.data());
    auto SideBar = Container->autoHideSideBar(sideBarLocation);

    // 如果侧边栏不可用或不对容器可见，则返回默认宽度
    if (!SideBar || !SideBar->isVisibleTo(Container))
    {
        return AutoHideAreaWidth;
    }
    else
    {
        // 如果侧边栏是水平方向的，则返回高度；否则返回宽度
        return (SideBar->orientation() == Qt::Horizontal) ? SideBar->height() : SideBar->width();
    }
}
//============================================================================

// 根据侧边栏的位置计算侧边栏鼠标区域的大小
int DockOverlayPrivate::sideBarMouseZone(SideBarLocation sideBarLocation)
{
    auto Container = qobject_cast<CDockContainerWidget*>(TargetWidget.data());
    auto SideBar = Container->autoHideSideBar(sideBarLocation);

    // 如果侧边栏不可用或不对容器可见，则返回默认鼠标区域大小
    if (!SideBar || !SideBar->isVisibleTo(Container))
    {
        return AutoHideAreaMouseZone;
    }
    else
    {
        // 如果侧边栏是水平方向的，则返回高度；否则返回宽度
        return (SideBar->orientation() == Qt::Horizontal) ? SideBar->height() : SideBar->width();
    }
}
//============================================================================

// CDockOverlay类的构造函数
CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
    QFrame(parent),
    d(new DockOverlayPrivate(this))
{
    d->Mode = Mode;
    d->Cross = new CDockOverlayCross(this);

    // 根据操作系统设置窗口标志
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
    setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
#else
    setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
#endif

    setWindowOpacity(1);
    setWindowTitle("DockOverlay");
    setAttribute(Qt::WA_NoSystemBackground);
    setAttribute(Qt::WA_TranslucentBackground);
    d->Cross->setVisible(false);
    setVisible(false);
}
//============================================================================

// CDockOverlay类的析构函数
CDockOverlay::~CDockOverlay()
{
    delete d;
}
//============================================================================

// 设置允许的停靠区域
void CDockOverlay::setAllowedAreas(DockWidgetAreas areas)
{
    // 如果允许的区域与当前区域相同，则返回
    if (areas == d->AllowedAreas)
    {
        return;
    }

    d->AllowedAreas = areas;
    d->Cross->reset();
}


//============================================================================
// 设置允许的区域
void CDockOverlay::setAllowedArea(DockWidgetArea area, bool Enable)
{
    // 保存旧的区域
    auto AreasOld = d->AllowedAreas;
    
    // 根据参数设置区域
    d->AllowedAreas.setFlag(area, Enable);
    
    // 如果区域发生变化，则重置交叉图标
    if (AreasOld != d->AllowedAreas)
    {
        d->Cross->reset();
    }
}
//============================================================================
// 获取允许的区域
DockWidgetAreas CDockOverlay::allowedAreas() const
{
    return d->AllowedAreas;
}
//============================================================================
// 获取鼠标下的放置区域
DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
{
    d->TabIndex = InvalidTabIndex;
    
    // 如果没有目标窗口，则返回无效的区域
    if (!d->TargetWidget)
    {
        return InvalidDockWidgetArea;
    }
    
    // 获取交叉图标的位置
    DockWidgetArea Result = d->Cross->cursorLocation();
    
    // 如果位置不是无效的区域，则返回结果
    if (Result != InvalidDockWidgetArea)
    {
        return Result;
    }
    
    // 获取光标的位置和目标窗口的类型
    auto CursorPos = QCursor::pos();
    auto DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data());
    
    // 如果目标窗口为空且自动隐藏功能被启用
    if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled))
    {
        auto Rect = rect();
        const QPoint pos = mapFromGlobal(QCursor::pos());
        
        // 判断光标位置是否在左侧自动隐藏区域内
        if ((pos.x() < d->sideBarMouseZone(SideBarLeft)) && d->AllowedAreas.testFlag(LeftAutoHideArea))
        {
            Result = LeftAutoHideArea;
        }
        // 判断光标位置是否在右侧自动隐藏区域内
        else if (pos.x() > (Rect.width() - d->sideBarMouseZone(SideBarRight)) && d->AllowedAreas.testFlag(RightAutoHideArea))
        {
            Result = RightAutoHideArea;
        }
        // 判断光标位置是否在顶部自动隐藏区域内
        else if (pos.y() < d->sideBarMouseZone(SideBarTop) && d->AllowedAreas.testFlag(TopAutoHideArea))
        {
            Result = TopAutoHideArea;
        }
        // 判断光标位置是否在底部自动隐藏区域内
        else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom)) && d->AllowedAreas.testFlag(BottomAutoHideArea))
        {
            Result = BottomAutoHideArea;
        }
        
        // 获取侧边栏位置
        auto SideBarLocation = ads::internal::toSideBarLocation(Result);
        
        // 如果侧边栏位置不是无，则获取自动隐藏侧边栏
        if (SideBarLocation != SideBarNone)
        {
            auto Container = qobject_cast<CDockContainerWidget*>(d->TargetWidget.data());
            auto SideBar = Container->autoHideSideBar(SideBarLocation);
            
            // 如果自动隐藏侧边栏可见，则获取插入索引
            if (SideBar->isVisible())
            {
                d->TabIndex = SideBar->tabInsertIndexAt(SideBar->mapFromGlobal(CursorPos));
            }
        }
        
        return Result;
    }
    // 如果目标窗口为空，则返回结果
    else if (!DockArea)
    {
        return Result;
    }
    
    // 如果中心区域允许放置且标题栏可见且鼠标在标题栏内
    if (DockArea->allowedAreas().testFlag(CenterDockWidgetArea)
        && !DockArea->titleBar()->isHidden()
        && DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(CursorPos)))
    {
        auto TabBar = DockArea->titleBar()->tabBar();
        d->TabIndex = TabBar->tabInsertIndexAt(TabBar->mapFromGlobal(CursorPos));
        return CenterDockWidgetArea;
    }
    
    return Result;
}
//============================================================================
// 获取光标下的选项卡索引
int CDockOverlay::tabIndexUnderCursor() const
{
    return d->TabIndex;
}
//============================================================================
// 获取光标下可见的放置区域
DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
{
    // 如果隐藏或者放置预览被禁用，则返回无效的区域
    if (isHidden() || !d->DropPreviewEnabled)
    {
        return InvalidDockWidgetArea;
    }
    else
    {
        return dropAreaUnderCursor();
    }
}
//============================================================================
// 显示覆盖层
DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
{
    // 如果目标窗口已经是当前目标窗口
    if (d->TargetWidget == target)
    {
        // 提示：可以在此处更新覆盖层的几何形状
        DockWidgetArea da = dropAreaUnderCursor();
        
        // 如果位置和上次位置不同，则重绘
        if (da != d->LastLocation)
        {
            repaint();
            d->LastLocation = da;
        }
        
        return da;
    }
    
    // 设置新的目标窗口
    d->TargetWidget = target;
    d->LastLocation = InvalidDockWidgetArea;
    
    // 移动覆盖层到目标窗口上方并显示
    hide();
    resize(target->size());
    QPoint TopLeft = target->mapToGlobal(target->rect().topLeft());
    move(TopLeft);
    show();
    
    // 更新交叉图标的位置和覆盖层图标
    d->Cross->updatePosition();
    d->Cross->updateOverlayIcons();
    
    return dropAreaUnderCursor();
}


//============================================================================
// 隐藏叠加层
void CDockOverlay::hideOverlay()
{
    hide(); // 隐藏叠加层
    d->TargetWidget.clear(); // 清空目标窗口
    d->LastLocation = InvalidDockWidgetArea; // 重置最后的位置
    d->DropAreaRect = QRect(); // 清空拖放区域矩形
}
//============================================================================
// 启用/禁用拖放预览
void CDockOverlay::enableDropPreview(bool Enable)
{
    d->DropPreviewEnabled = Enable; // 设置拖放预览是否启用
    update(); // 更新叠加层
}
//============================================================================
// 获取拖放预览是否启用
bool CDockOverlay::dropPreviewEnabled() const
{
    return d->DropPreviewEnabled; // 返回拖放预览是否启用
}
//============================================================================
// 绘制事件
void CDockOverlay::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    // 根据位置绘制矩形
    if (!d->DropPreviewEnabled)
    {
        d->DropAreaRect = QRect();
        return;
    }

    QRect r = rect();
    const DockWidgetArea da = dropAreaUnderCursor();
    double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? 3 : 2;

    switch (da)
    {
        case TopDockWidgetArea: r.setHeight(r.height() / Factor); break;
        case RightDockWidgetArea: r.setX(r.width() * (1 - 1 / Factor)); break;
        case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break;
        case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break;
        case CenterDockWidgetArea: r = rect(); break;
        case LeftAutoHideArea: r.setWidth(d->sideBarOverlaySize(SideBarLeft)); break;
        case RightAutoHideArea: r.setX(r.width() - d->sideBarOverlaySize(SideBarRight)); break;
        case TopAutoHideArea: r.setHeight(d->sideBarOverlaySize(SideBarTop)); break;
        case BottomAutoHideArea: r.setY(r.height() - d->sideBarOverlaySize(SideBarBottom)); break;
        default: return;
    }

    QPainter painter(this);
    QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
    QPen Pen = painter.pen();
    Pen.setColor(Color.darker(120));
    Pen.setStyle(Qt::SolidLine);
    Pen.setWidth(1);
    Pen.setCosmetic(true);
    painter.setPen(Pen);
    Color = Color.lighter(130);
    Color.setAlpha(64);
    painter.setBrush(Color);
    painter.drawRect(r.adjusted(0, 0, -1, -1));
    d->DropAreaRect = r;
}
//============================================================================
// 获取拖放叠加层矩形
QRect CDockOverlay::dropOverlayRect() const
{
    return d->DropAreaRect; // 返回拖放叠加层矩形
}
//============================================================================
// 显示事件
void CDockOverlay::showEvent(QShowEvent* e)
{
    d->Cross->show(); // 显示交叉线
    QFrame::showEvent(e);
}
//============================================================================
// 隐藏事件
void CDockOverlay::hideEvent(QHideEvent* e)
{
    d->Cross->hide(); // 隐藏交叉线
    QFrame::hideEvent(e);
}
//============================================================================
// 事件处理
bool CDockOverlay::event(QEvent *e)
{
    bool Result = Super::event(e);
    if (e->type() == QEvent::Polish)
    {
        d->Cross->setupOverlayCross(d->Mode); // 设置交叉线
    }
    return Result;
}


//============================================================================
// areaAlignment
// 返回给定停靠区域的对齐标志
//============================================================================
static int areaAlignment(const DockWidgetArea area)
{
    switch (area)
    {
        case TopDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignBottom; // 水平居中，垂直底部对齐
        case RightDockWidgetArea: return (int) Qt::AlignLeft | Qt::AlignVCenter; // 左对齐，垂直居中
        case BottomDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignTop; // 水平居中，垂直顶部对齐
        case LeftDockWidgetArea: return (int) Qt::AlignRight | Qt::AlignVCenter; // 右对齐，垂直居中
        case CenterDockWidgetArea:  return (int) Qt::AlignCenter; // 居中对齐
        default: return Qt::AlignCenter;
    }
}

//============================================================================
// DockOverlayCrossPrivate
//============================================================================

// 返回给定停靠区域的网格位置
QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area)
{
    if (CDockOverlay::ModeDockAreaOverlay == Mode)
    {
        switch (area)
        {
            case TopDockWidgetArea: return QPoint(1, 2); // 第1行，第2列
            case RightDockWidgetArea: return QPoint(2, 3); // 第2行，第3列
            case BottomDockWidgetArea: return QPoint(3, 2); // 第3行，第2列
            case LeftDockWidgetArea: return QPoint(2, 1); // 第2行，第1列
            case CenterDockWidgetArea: return QPoint(2, 2); // 第2行，第2列
            default: return QPoint();
        }
    }
    else
    {
        switch (area)
        {
            case TopDockWidgetArea: return QPoint(0, 2); // 第0行，第2列
            case RightDockWidgetArea: return QPoint(2, 4); // 第2行，第4列
            case BottomDockWidgetArea: return QPoint(4, 2); // 第4行，第2列
            case LeftDockWidgetArea: return QPoint(2, 0); // 第2行，第0列
            case CenterDockWidgetArea: return QPoint(2, 2); // 第2行，第2列
            default: return QPoint();
        }
    }
}

//============================================================================
// CDockOverlayCross
//============================================================================

// 构造函数
CDockOverlayCross::CDockOverlayCross(CDockOverlay* overlay) :
    QWidget(overlay->parentWidget()),
    d(new DockOverlayCrossPrivate(this))
{
    d->DockOverlay = overlay;
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
    setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
#else
    setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
#endif
    setWindowTitle("DockOverlayCross");
    setAttribute(Qt::WA_TranslucentBackground);
    d->GridLayout = new QGridLayout();
    d->GridLayout->setSpacing(0);
    setLayout(d->GridLayout);
}

// 析构函数
CDockOverlayCross::~CDockOverlayCross()
{
    delete d;
}

// 设置叠加层交叉图标的模式
void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
{
    d->Mode = Mode;
    QHash<DockWidgetArea, QWidget*> areaWidgets;
    areaWidgets.insert(TopDockWidgetArea, d->createDropIndicatorWidget(TopDockWidgetArea, Mode));
    areaWidgets.insert(RightDockWidgetArea, d->createDropIndicatorWidget(RightDockWidgetArea, Mode));
    areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
    areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
    areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode));
#if QT_VERSION >= 0x050600
    d->LastDevicePixelRatio = devicePixelRatioF();
#else
    d->LastDevicePixelRatio = devicePixelRatio();
#endif
    setAreaWidgets(areaWidgets);
    d->UpdateRequired = false;
}

// 更新叠加层交叉图标的图标
void CDockOverlayCross::updateOverlayIcons()
{
    if (windowHandle()->devicePixelRatio() == d->LastDevicePixelRatio)
    {
        return;
    }
    for (auto Widget : d->DropIndicatorWidgets)
    {
        d->updateDropIndicatorIcon(Widget);
    }
#if QT_VERSION >= 0x050600
    d->LastDevicePixelRatio = devicePixelRatioF();
#else
    d->LastDevicePixelRatio = devicePixelRatio();
#endif
}

// 设置图标的颜色
void CDockOverlayCross::setIconColor(eIconColor ColorIndex, const QColor& Color)
{
    d->IconColors[ColorIndex] = Color;
    d->UpdateRequired = true;
}

// 获取图标的颜色
QColor CDockOverlayCross::iconColor(eIconColor ColorIndex) const
{
    return d->IconColors[ColorIndex];
}


void CDockOverlayCross::setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets)
{
    // 删除旧的小部件
    QMutableHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
    while (i.hasNext()) {
        i.next();
        QWidget* widget = i.value();
        d->GridLayout->removeWidget(widget);
        delete widget;
        i.remove();
    }

    // 将新的小部件插入到网格中
    d->DropIndicatorWidgets = widgets;
    QHashIterator<DockWidgetArea, QWidget*> i2(d->DropIndicatorWidgets);
    while (i2.hasNext()) {
        i2.next();
        const DockWidgetArea area = i2.key();
        QWidget* widget = i2.value();
        QPoint p = d->areaGridPosition(area);
        d->GridLayout->addWidget(widget, p.x(), p.y(), (Qt::Alignment) areaAlignment(area));
    }

    // 根据模式设置网格布局的属性
    if (CDockOverlay::ModeDockAreaOverlay == d->Mode) {
        d->GridLayout->setContentsMargins(0, 0, 0, 0);
        d->GridLayout->setRowStretch(0, 1);
        d->GridLayout->setRowStretch(1, 0);
        d->GridLayout->setRowStretch(2, 0);
        d->GridLayout->setRowStretch(3, 0);
        d->GridLayout->setRowStretch(4, 1);
        d->GridLayout->setColumnStretch(0, 1);
        d->GridLayout->setColumnStretch(1, 0);
        d->GridLayout->setColumnStretch(2, 0);
        d->GridLayout->setColumnStretch(3, 0);
        d->GridLayout->setColumnStretch(4, 1);
    } else {
        d->GridLayout->setContentsMargins(4, 4, 4, 4);
        d->GridLayout->setRowStretch(0, 0);
        d->GridLayout->setRowStretch(1, 1);
        d->GridLayout->setRowStretch(2, 1);
        d->GridLayout->setRowStretch(3, 1);
        d->GridLayout->setRowStretch(4, 0);
        d->GridLayout->setColumnStretch(0, 0);
        d->GridLayout->setColumnStretch(1, 1);
        d->GridLayout->setColumnStretch(2, 1);
        d->GridLayout->setColumnStretch(3, 1);
        d->GridLayout->setColumnStretch(4, 0);
    }

    reset();
}

DockWidgetArea CDockOverlayCross::cursorLocation() const
{
    const QPoint pos = mapFromGlobal(QCursor::pos());
    QHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
    while (i.hasNext()) {
        i.next();
        if (d->DockOverlay->allowedAreas().testFlag(i.key())
            && i.value()
            && i.value()->isVisible()
            && i.value()->geometry().contains(pos)) {
            return i.key();
        }
    }

    return InvalidDockWidgetArea;
}

void CDockOverlayCross::showEvent(QShowEvent*)
{
    if (d->UpdateRequired) {
        setupOverlayCross(d->Mode);
    }

    updatePosition();
}

void CDockOverlayCross::updatePosition()
{
    resize(d->DockOverlay->size());
    QPoint TopLeft = d->DockOverlay->pos();
    QPoint Offest((this->width() - d->DockOverlay->width()) / 2,
        (this->height() - d->DockOverlay->height()) / 2);
    QPoint CrossTopLeft = TopLeft - Offest;
    move(CrossTopLeft);
}

void CDockOverlayCross::reset()
{
    QList<DockWidgetArea> allAreas;
    allAreas << TopDockWidgetArea << RightDockWidgetArea
        << BottomDockWidgetArea << LeftDockWidgetArea << CenterDockWidgetArea;
    const DockWidgetAreas allowedAreas = d->DockOverlay->allowedAreas();

    // 根据允许的区域更新小部件的可见性
    for (int i = 0; i < allAreas.count(); ++i) {
        QPoint p = d->areaGridPosition(allAreas.at(i));
        QLayoutItem* item = d->GridLayout->itemAtPosition(p.x(), p.y());
        QWidget* w = nullptr;
        if (item && (w = item->widget()) != nullptr) {
            w->setVisible(allowedAreas.testFlag(allAreas.at(i)));
        }
    }
}

void CDockOverlayCross::setIconColors(const QString& Colors)
{
    static const QMap<QString, int> ColorCompenentStringMap{
        {"Frame", CDockOverlayCross::FrameColor},
        {"Background", CDockOverlayCross::WindowBackgroundColor},
        {"Overlay", CDockOverlayCross::OverlayColor},
        {"Arrow", CDockOverlayCross::ArrowColor},
        {"Shadow", CDockOverlayCross::ShadowColor}
    };

    auto ColorList = Colors.split(' ', Qt::SkipEmptyParts);
    for (const auto& ColorListEntry : ColorList) {
        auto ComponentColor = ColorListEntry.split('=', Qt::SkipEmptyParts);
        int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
        if (Component < 0) {
            continue;
        }

        d->IconColors[Component] = QColor(ComponentColor[1]);
    }

    d->UpdateRequired = true;
}

QString CDockOverlayCross::iconColors() const
{
    return QString();
}



} // namespace ads
//----------------------------------------------------------------------------

